﻿using BaseData.API.Read.Applications.Commands;
using BaseData.API.Read.Dtos;
using BaseData.Domain;
using BaseData.ErrorCode;
using BaseData.Infrastructure.Interfaces;
using MD5Hash;
using MediatR;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace BaseData.API.Read.Applications.CommandHandlers
{
    /// <summary>
    /// 登录命令类
    /// </summary>
    public class LoginCommandHandler:IRequestHandler<LoginCommand,ApiResult<UserDTO>>
    {
        private readonly IBaseRepository<User> userRep;
        private readonly IBaseRepository<Role> roleRep;
        private readonly IBaseRepository<UserRoleRelation> userRoleRep;
        private readonly IConfiguration config;
        private readonly IBaseRepository<Permission> permissionRep;
        private readonly IBaseRepository<RolePermissionRelation> rolePermissionRep;

        public LoginCommandHandler(IBaseRepository<User> userRep,IBaseRepository<Role> roleRep,IBaseRepository<UserRoleRelation> userRoleRep,IConfiguration config,
            IBaseRepository<Permission> permissionRep,IBaseRepository<RolePermissionRelation> rolePermissionRep)
        {
            this.userRep = userRep;
            this.roleRep = roleRep;
            this.userRoleRep = userRoleRep;
            this.config = config;
            this.permissionRep = permissionRep;
            this.rolePermissionRep = rolePermissionRep;
        }

        public Task<ApiResult<UserDTO>> Handle(LoginCommand request, CancellationToken cancellationToken)
        {
            ApiResult<UserDTO> result=new ApiResult<UserDTO>();
            result.Code = ApiEnum.登录成功;
            result.Message = ApiEnum.登录成功.ToString();

            try
            {
                //MD5
                request.UserPass = request.UserPass.GetMD5();
                var list = from a in userRep.GetAll()
                           join b in userRoleRep.GetAll()
                           on a.UserId equals b.UserId
                           join c in roleRep.GetAll()
                           on b.RoleId equals c.RoleId
                           where a.UserName == request.UserName && a.UserPass == request.UserPass
                           select new UserDTO
                           {
                               UserId=a.UserId,
                               UserName=a.UserName,
                               UserNickname=a.UserNickname,
                               RoleId=c.RoleId,
                               RoleName=c.RoleName
                           };
                var entity = list.FirstOrDefault();
                if(entity==null)
                {
                    throw new Exception("用户名错误或者密码不匹配!!!");
                }
                entity.Token = CreateTokenString(entity);
                var permission = from a in roleRep.GetAll()
                                 join b in rolePermissionRep.GetAll()
                                 on a.RoleId equals b.RoleId
                                 join c in permissionRep.GetAll()
                                 on b.PermissionId equals c.PermissionId
                                 where a.RoleId==entity.RoleId
                                 select new Permission
                                 {
                                     PermissionId=c.PermissionId,
                                     PermissionName=c.PermissionName,
                                     PermissionUrl=c.PermissionUrl,
                                     Status=c.Status,
                                     CreateTime=c.CreateTime,
                                     IsDel=c.IsDel,
                                 };
                entity.Permissions=permission.ToList();

                result.Data = entity;

            }
            catch (Exception ex)
            {
                result.Code = ApiEnum.登录失败;
                result.Message = ApiEnum.登录失败.ToString()+":"+ex.Message;
            }

            return Task.FromResult(result);
        }
        private string CreateTokenString(UserDTO Dto)
        {
            //私钥
            var secretByte = Encoding.UTF8.GetBytes("kdsfldsflkdslkflkdsflkdslfdslkflk");
            // 非对称加密
            var signingKey = new SymmetricSecurityKey(secretByte);
            // 使用256 生成数字签名
            var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256);

            var claims = new Claim[]
            {
                new Claim("UserId",Dto.UserId.ToString()),
                new Claim("UserName",Dto.UserName),
                new Claim("UserNickname",Dto.UserNickname),
                new Claim("RoleId",Dto.RoleId.ToString()),
                new Claim("RoleName",Dto.RoleName),
            };

            // 生成Token
            var token = new JwtSecurityToken(
                claims:claims,
                issuer: "BeiJingBW",
                audience: "BeiJingBW",
                expires: DateTime.Now.AddDays(1), // 一天后过期
                signingCredentials: signingCredentials
            );
            // 生成token 字符串
            var strToken = new JwtSecurityTokenHandler().WriteToken(token);
            return strToken;
        }

    }
}
